
using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading.RateLimiting;
using LyxWaf.Utils;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;

namespace LyxWaf.Services.WafInfo;

public interface IWafInfoService
{
    public WafInfoOptions GetOptions(); 
    public X509Certificate2 GetCertByName(string name);
}


public class WafInfoService : IWafInfoService
{
    private WafInfoOptions _options;
    private readonly IMemoryCache _cache;
    private readonly ILogger<WafInfoService> _logger;

    private readonly Dictionary<string, X509Certificate2> certs = [];
    public WafInfoService(
        IOptionsMonitor<WafInfoOptions> options, IMemoryCache cache,
        ILogger<WafInfoService> logger)
    {
        _options = options.CurrentValue;
        // 可以订阅变更，但需注意生命周期和内存泄漏
        options.OnChange(newConfig =>
        {
            _options = newConfig;
            BuildCerts();
        });
        BuildCerts();
        _cache = cache;
        _logger = logger;
    }

    public WafInfoOptions GetOptions()
    {
        return _options;
    }

    public void BuildCerts()
    {
        foreach (var url in _options.Certs)
        {
            X509Certificate2 cert = CertUtils.LoadFromFile(url.PemFile, url.KeyFile);
            certs.Remove(url.Host);
            certs.Add(url.Host, cert);
        }
    }

    public X509Certificate2 GetCertByName(string name)
    {
        switch (certs.Count)
        {
            case 0:
                {
                    throw new Exception("不存在任何证书配置");
                }
            case 1:
                {
                    return certs.First().Value;
                }
            default:
                {
                    foreach (var (k, v) in certs)
                    {
                        if (k == name)
                        {
                            return v;
                        }
                        if (k.StartsWith("*.") && name.EndsWith(k[2..]))
                        {
                            return v;
                        }
                    }
                    return certs.First().Value;
                }
        }
    }
}